﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections.ObjectModel;

namespace SuperKinhLuan.Games.PeerChess.GameLib
{
    public abstract class Board
    {
        private ObservableCollection<Piece> pieces;
        private Piece[,] map;
        private int row, column;

        public ObservableCollection<Piece> Pieces
        {
            get { return this.pieces; }
        }

        public Piece this[int row, int column]
        {
            get { return this.map[row, column]; }
        }

        protected Board(int row, int column)
        {
            if (row <= 0 || row > 100)
            {
                throw new ArgumentOutOfRangeException("row");
            }

            if (column <= 0 || column > 100)
            {
                throw new ArgumentOutOfRangeException("column");
            }

            this.pieces = new ObservableCollection<Piece>();
            
            this.row = row;
            this.column = column;
            this.map = new Piece[row, column];
        }

        //protected Board(int row, int column, IEnumerable<Piece> pieces) : this(row, column)
        //{
        //    if (pieces == null)
        //    {
        //        throw new ArgumentNullException("pieces");
        //    }

        //    Debug.Assert(this.pieces != null);
        //    this.pieces.AddRange(pieces);
        //}

        public void AddPiece(Piece piece)
        {
            if (piece == null)
            {
                throw new ArgumentNullException("piece");
            }

            Position p = piece.Position;
            if (p.Column < 0 || p.Column >= this.column || 
                p.Row < 0 || p.Row >= this.row)
            {
                throw new ArgumentException(
                    "The position of the added piece is outside the boundary of the board.");
            }

            if (this.map[p.Row, p.Column] != null)
            {
                throw new ArgumentException(
                    "The location of the added piece is already occupied by another piece.");
            }

            if (piece.Board != this)
            {
                this.map[p.Row, p.Column] = piece;
                piece.Board = this;
                this.pieces.Add(piece);
            }
        }

        public void RemovePiece(Piece piece)
        {
            if (piece != null && piece.Board == this)
            {
                Position p = piece.Position;
                this.map[p.Row, p.Column] = null;
                piece.Board = null;
                this.pieces.Remove(piece);
            }
        }

        public void ClearPieces()
        {
            foreach (Piece p in this.pieces)
            {
                p.Board = null;
            }
            
            for (int i = 0; i < this.row; i++)
            {
                for (int j = 0; j < this.column; j++)
                {
                    this.map[i, j] = null;
                }
            }

            this.pieces.Clear();
        }
    }
}